package com.lazyboyl.sharding.proxy.net.response;

import com.lazyboyl.sharding.proxy.net.frontend.FrontendConnection;
import com.lazyboyl.sharding.proxy.net.proto.mysql.EOFPacket;
import com.lazyboyl.sharding.proxy.net.proto.mysql.FieldPacket;
import com.lazyboyl.sharding.proxy.net.proto.mysql.ResultSetHeaderPacket;
import com.lazyboyl.sharding.proxy.net.proto.mysql.RowDataPacket;
import com.lazyboyl.sharding.proxy.net.proto.util.ByteUtil;
import com.lazyboyl.sharding.proxy.net.proto.util.Fields;
import com.lazyboyl.sharding.proxy.net.proto.util.PacketUtil;
import com.lazyboyl.sharding.proxy.net.proto.util.StringUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public class QueryResult {

    public static void response(FrontendConnection c, String sql) {
        List<Map<String, Object>> queryList = c.getCurrencyService().executeCurrencySql(sql);
        Map<String, Object> queryResult = queryList.get(0);
        int FIELD_COUNT = queryResult.size();
        ResultSetHeaderPacket header = PacketUtil.getHeader(FIELD_COUNT);
        FieldPacket[] fields = new FieldPacket[FIELD_COUNT];
        EOFPacket eof = new EOFPacket();
        byte packetId = 0;
        int i = 0;
        header.packetId = ++packetId;
        for (Map.Entry<String, Object> entry : queryResult.entrySet()) {
            fields[i] = PacketUtil.getField(entry.getKey(), Fields.FIELD_TYPE_VAR_STRING);
            fields[i++].packetId = ++packetId;
        }
        eof.packetId = ++packetId;

        ChannelHandlerContext ctx = c.getCtx();
        ByteBuf buffer = ctx.alloc().buffer();
        buffer = header.writeBuf(buffer, ctx);
        for (FieldPacket field : fields) {
            buffer = field.writeBuf(buffer, ctx);
        }
        buffer = eof.writeBuf(buffer, ctx);
        byte packetIdNew = eof.packetId;
        for (Map<String, Object> map : queryList) {
            RowDataPacket row = new RowDataPacket(FIELD_COUNT);
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                Object obj = map.get(entry.getKey());
                if (obj instanceof String) {
                    row.add(StringUtil.encode((String) obj, "gbk"));
                } else if (obj instanceof LocalDateTime) {
                    DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    String localTime = df.format((LocalDateTime) obj);
                    row.add(StringUtil.encode(localTime, "gbk"));
                } else if (obj instanceof Date) {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String localTime = sdf.format((Date) obj);
                    row.add(StringUtil.encode(localTime, "gbk"));
                } else if (obj instanceof Long) {
                    Long l = (Long) obj;
                    row.add(StringUtil.encode(Long.toString(l), "gbk"));
                } else if (obj instanceof Integer) {
                    Integer integer = (Integer) obj;
                    row.add(StringUtil.encode(Integer.toString(integer), "gbk"));
                } else {
                    row.add(ByteUtil.getBytes(obj));
                }
            }
            row.packetId = ++packetIdNew;
            buffer = row.writeBuf(buffer, ctx);
        }

        EOFPacket lastEof = new EOFPacket();
        lastEof.packetId = ++packetIdNew;
        buffer = lastEof.writeBuf(buffer, ctx);
        ctx.writeAndFlush(buffer);
    }

    public static void response(FrontendConnection c) {
        List<Map<String, String>> queryList = new ArrayList<>();
        Map<String, String> queryResult = new HashMap<>();
        queryResult.put("user_name", "林泽锋");
        queryResult.put("age", "18");
        queryResult.put("birth_date", "2021-07-01 14:38:50");
        queryList.add(queryResult);
        Map<String, String> queryResult1 = new HashMap<>();
        queryResult1.put("user_name", "林泽锋1");
        queryResult1.put("age", "19");
        queryResult1.put("birth_date", "2021-07-01 14:38:51");
        queryList.add(queryResult1);
        int FIELD_COUNT = queryResult.size();
        ResultSetHeaderPacket header = PacketUtil.getHeader(FIELD_COUNT);
        FieldPacket[] fields = new FieldPacket[FIELD_COUNT];
        EOFPacket eof = new EOFPacket();
        byte packetId = 0;
        int i = 0;
        header.packetId = ++packetId;
        for (Map.Entry<String, String> entry : queryResult.entrySet()) {
            fields[i] = PacketUtil.getField(entry.getKey(), Fields.FIELD_TYPE_VAR_STRING);
            fields[i++].packetId = ++packetId;
        }
        eof.packetId = ++packetId;

        ChannelHandlerContext ctx = c.getCtx();
        ByteBuf buffer = ctx.alloc().buffer();
        buffer = header.writeBuf(buffer, ctx);
        for (FieldPacket field : fields) {
            buffer = field.writeBuf(buffer, ctx);
        }
        buffer = eof.writeBuf(buffer, ctx);
        byte packetIdNew = eof.packetId;
        for (Map<String, String> map : queryList) {
            RowDataPacket row = new RowDataPacket(FIELD_COUNT);
            row.add(StringUtil.encode(map.get("user_name"), "gbk"));
            row.add(StringUtil.encode(map.get("age"), "gbk"));
            row.add(StringUtil.encode(map.get("birth_date"), "gbk"));
            row.packetId = ++packetIdNew;
            buffer = row.writeBuf(buffer, ctx);
        }

        EOFPacket lastEof = new EOFPacket();
        lastEof.packetId = ++packetIdNew;
        buffer = lastEof.writeBuf(buffer, ctx);
        ctx.writeAndFlush(buffer);
    }

//    private static final int FIELD_COUNT = 2;
//    private static final ResultSetHeaderPacket header = PacketUtil.getHeader(FIELD_COUNT);
//    private static final FieldPacket[] fields = new FieldPacket[FIELD_COUNT];
//    private static final EOFPacket eof = new EOFPacket();
//
//    static {
//        int i = 0;
//        byte packetId = 0;
//        header.packetId = ++packetId;
//
//        fields[0] = PacketUtil.getField("TABLE", Fields.FIELD_TYPE_VAR_STRING);
//        fields[0].packetId = ++packetId;
//        fields[1] = PacketUtil.getField("TABLE1", Fields.FIELD_TYPE_VAR_STRING);
//        fields[1].packetId = ++packetId;
//
//        eof.packetId = ++packetId;
//    }
//
//    public static void response(FrontendConnection connection) {
//        ChannelHandlerContext ctx = connection.getCtx();
//        ByteBuf buffer = ctx.alloc().buffer();
//
//        // write header
//        buffer = header.writeBuf(buffer, ctx);
//
//        // write fields
//        for (FieldPacket field : fields) {
//            buffer = field.writeBuf(buffer, ctx);
//        }
//
//        // write eof
//        buffer = eof.writeBuf(buffer, ctx);
//
//        // write rows
//        byte packetId = eof.packetId;
//
//        for (String name : getTables()) {
//            RowDataPacket row = new RowDataPacket(FIELD_COUNT);
//            row.add(StringUtil.encode(name, "UTF-8"));
//            row.add(StringUtil.encode(name, "UTF-8"));
//            row.packetId = ++packetId;
//            buffer = row.writeBuf(buffer, ctx);
//        }
//
//        // write lastEof
//        EOFPacket lastEof = new EOFPacket();
//        lastEof.packetId = ++packetId;
//        buffer = lastEof.writeBuf(buffer, ctx);
//
//        // write buffer
//        ctx.writeAndFlush(buffer);
//    }
//
//    private static List<String> getTables() {
//        List<String> list = new ArrayList<String>();
//        list.add("t_print_info");
//        list.add("t_dev_details");
//        return list;
//    }

}
